package cn.mymall.service.impl;

import cn.mymall.constant.CachedKey;
import cn.mymall.constant.MallConstant;
import cn.mymall.constant.OrderStatusConstant;
import cn.mymall.entity.*;
import cn.mymall.entity.mall.CartItem;
import cn.mymall.entity.mall.Product;
import cn.mymall.entity.mall.Sku;
import cn.mymall.mapper.TradeOrderMapper;
import cn.mymall.redis.RedisHelper;
import cn.mymall.service.*;
import cn.mymall.service.mall.ICartItemService;
import cn.mymall.service.mall.IProductService;
import cn.mymall.service.mall.ISkuService;
import cn.mymall.util.BeanUtil;
import cn.mymall.util.DateUtil;
import cn.mymall.util.FastJsonUtil;
import cn.mymall.util.RandomUtil;
import cn.mymall.vo.order.CreateMallOrderVo;
import cn.mymall.vo.order.OrderSearchVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liqilun
 * @since 2024-03-23
 */
@Service
public class TradeOrderServiceImpl extends ServiceImpl<TradeOrderMapper, TradeOrder> implements ITradeOrderService {
    @Autowired
    private IProductService productService;
    @Autowired
    private ISkuService skuService;
    @Autowired
    private ICartItemService cartItemService;
    @Autowired
    private IMemberService memberService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private IOrderItemService orderItemService;
    @Autowired
    private IMemberAddressOrderService memberAddressOrderService;

    @Autowired
    protected RedisHelper redisHelper;
    private boolean supportDelivery(Product product, MemberAddress address){
        if(StringUtils.isBlank(product.getDeliveryProvincecodes())) {
            return true;
        }
        if(StringUtils.equalsIgnoreCase(product.getDeliveryProvinceMode(), MallConstant.Delivery_Province_Mode_include)){
            List<Integer> provinceIdList = BeanUtil.getIdList(product.getDeliveryProvincecodes());
            if(!provinceIdList.contains(address.getProvinceId())){
                return false;
            }
        }else if(StringUtils.equalsIgnoreCase(product.getDeliveryProvinceMode(), MallConstant.Delivery_Province_Mode_exclude)){
            List<Integer> provinceIdList = BeanUtil.getIdList(product.getDeliveryProvincecodes());
            if(provinceIdList.contains(address.getProvinceId())){
                return false;
            }
        }
        return true;
    }
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public TradeOrder createOrder(CreateMallOrderVo orderVo) throws OrderException {
        Member meber = memberService.getById(orderVo.getMemberId());
        Product product = productService.getById(orderVo.getProductId());
        Sku sku = skuService.getById(orderVo.getSkuId());

        MemberAddress address = orderVo.getMemberAddress();
        if(!supportDelivery(product, address)){
            throw new OrderException("不支持的配送范围");
        }
        if (!product.hasBooking()) {
            throw new OrderException("商品暂时不能购买！");
        }
        if (!sku.hasBooking()) {
            throw new OrderException("规格:" + sku.getName() + "暂时不能购买！");
        }
        if(product.getMaxCnt()!=null){
            if(product.getMaxCnt()-orderVo.getQty()<0){
                throw new OrderException("该商品每次最大购买数量:"+product.getMaxCnt());
            }
            if(product.getWithinHour()!=null && product.getWithinHour()>0){
                String key = CachedKey.getJoinKey("vp", product.getId(), orderVo.getMemberId());
                Integer buyCnt = (Integer) redisHelper.get(key);
                if(buyCnt!=null && (buyCnt+ orderVo.getQty())>product.getMaxCnt()){
                    throw new OrderException("该商品"+product.getWithinHour()+"小时内最多购买数量:"+product.getMaxCnt());
                }
            }
        }
        Map<String, String> otherMap = new HashMap<String, String>();
        if (StringUtils.isNotBlank(orderVo.getMemberRemark())) {
            otherMap.put("memberRemark", orderVo.getMemberRemark());
        }
        if (StringUtils.isNotBlank(product.getPartnerGoodsId())) {
            otherMap.put("partnerGoodsId", product.getPartnerGoodsId());
            otherMap.put("showMemberAddress", "false");
        }
        if (StringUtils.isNotBlank(product.getPartnerCode())) {
            otherMap.put("partnerCode", product.getPartnerCode());
        }

        BigDecimal expressFee = productService.getShippingFeeByProduct(meber, product, sku, orderVo.getQty(), address.getProvinceId()).getFee();
        TradeOrder order = new TradeOrder();
        order.setTradeno(DateUtil.format(DateUtil.getCurFullTimestamp(),"yyMMddHHmmss") + RandomUtil.getDigitalRandomString(4));
        order.setAddTime(DateUtil.getCurFullTimestamp());
        order.setOrderAmount(sku.getSellPrice().multiply(new BigDecimal(orderVo.getQty())));
        order.setSettleAmount(sku.getCostPrice().multiply(new BigDecimal(orderVo.getQty())));
        order.setDiscount(new BigDecimal(0));
        order.setCashPay(new BigDecimal(0));
        order.setExpressFee(expressFee);
        order.setMemberId(orderVo.getMemberId());
        order.setMobile(orderVo.getMobile());
        order.setOrderStatus(OrderStatusConstant.NEW);
        order.setPayStatus(OrderStatusConstant.NEW);

        //过期时间
        Timestamp expireTime = DateUtil.addMinute(order.getAddTime(), 30);
        order.setExpireTime(expireTime);
        order.setIp(orderVo.getIp());
        order.setOtherinfo("{}");
        save(order);

        OrderItem orderItem = new OrderItem(product, sku, orderVo.getQty(), order);
        orderItemService.save(orderItem);

        MemberAddressOrder memberAddressOrder = new MemberAddressOrder();
        memberAddressOrder.setOrderId(order.getId());
        BeanUtil.copyProperties(memberAddressOrder, address);
        memberAddressOrderService.save(memberAddressOrder);

        return order;
    }

    @Override@Transactional
    public TradeOrder createOrderByCart(CreateMallOrderVo orderVo, List<CartItem> cartItemList) throws OrderException {
        Member member = memberService.getById(orderVo.getMemberId());
        MemberAddress address = orderVo.getMemberAddress();
        Map<String, String> otherMap = new HashMap<String, String>();
        otherMap.put("cart", "Y");
        TradeOrder order = new TradeOrder();
        order.setTradeno(DateUtil.format(DateUtil.getCurFullTimestamp(),"yyMMddHHmmss") + RandomUtil.getDigitalRandomString(4));
        order.setAddTime(DateUtil.getCurFullTimestamp());
        order.setMemberId(orderVo.getMemberId());
        order.setMobile(orderVo.getMobile());
        order.setIp(orderVo.getIp());
        order.setOrderStatus(OrderStatusConstant.NEW);
        order.setPayStatus(OrderStatusConstant.NEW);
        Timestamp expireTime = DateUtil.addMinute(order.getAddTime(), 30);
        order.setExpireTime(expireTime);
        BigDecimal orderAmount = new BigDecimal(0);
        BigDecimal settleAmount = new BigDecimal(0);
        order.setDiscount(new BigDecimal(0));
        order.setCashPay(new BigDecimal(0));
        int qty = 0;
        List<Integer> categoryIdList = new ArrayList<>();
        Map<Integer, Product> productMap = new HashMap<>();
        Map<Integer, Sku> skuMap = new HashMap<>();
        for (CartItem cartItem : cartItemList) {
            if (!cartItem.getMemberId().equals(orderVo.getMemberId())) {
                throw new OrderException("非法操作");
            }
            qty = qty + cartItem.getQty();
            Sku sku = skuService.getById(cartItem.getSkuId());
            Product product = productService.getById(sku.getProductId());

            if(!supportDelivery(product, address)){
                throw new OrderException("不支持的配送范围");
            }
            if (!product.hasBooking()) {
                throw new OrderException("【" + product.getName() + "】暂时不能购买！");
            }
            if (!sku.hasBooking()) {
                throw new OrderException("【" + product.getName() + "】规格:" + sku.getName() + "暂时不能购买！");
            }
            if(product.getMaxCnt()!=null){
                if(product.getMaxCnt()-cartItem.getQty()<0){
                    throw new OrderException("【" + product.getName() + "】每次最大购买数量:"+product.getMaxCnt());
                }
                if(product.getWithinHour()!=null && product.getWithinHour()>0){
                    String key = CachedKey.getJoinKey("vp", product.getId(), orderVo.getMemberId());
                    Integer buyCnt = (Integer) redisHelper.get(key);
                    if(buyCnt!=null && (buyCnt+ cartItem.getQty())>product.getMaxCnt()){
                        throw new OrderException("【" + product.getName() + "】"+product.getWithinHour()+"小时内最多购买数量:"+product.getMaxCnt());
                    }
                }
            }

            orderAmount = orderAmount.add(sku.getSellPrice().multiply(new BigDecimal(cartItem.getQty())));
            settleAmount = settleAmount.add(sku.getCostPrice().multiply(new BigDecimal(cartItem.getQty())));
            skuMap.put(sku.getId(), sku);
            productMap.put(product.getId(), product);
            categoryIdList.add(product.getCategoryId());
        }

        order.setExpressFee(BigDecimal.ZERO);
        order.setOrderAmount(orderAmount);
        order.setSettleAmount(settleAmount);
        order.setOtherinfo(FastJsonUtil.toJsonString(otherMap));
        save(order);
        for (CartItem cartItem : cartItemList) {
            Sku sku = skuMap.get(cartItem.getSkuId());
            Product product = productMap.get(cartItem.getProductId());
            OrderItem orderItem = new OrderItem(product, sku, cartItem.getQty(), order);
            orderItemService.save(orderItem);
            cartItemService.removeById(cartItem.getId());
        }
        MemberAddressOrder memberAddressOrder = new MemberAddressOrder();
        memberAddressOrder.setOrderId(order.getId());
        BeanUtil.copyProperties(memberAddressOrder, address);
        memberAddressOrderService.save(memberAddressOrder);

        return order;
    }

    @Override
    public Page<TradeOrder> getPageList(OrderSearchVo reqVo) {
        QueryWrapper<TradeOrder> queryWrapper = new QueryWrapper();
        if (StringUtils.isNotBlank(reqVo.getMobile())) {
            queryWrapper.eq("mobile", reqVo.getMobile());
        }
        if (StringUtils.isNotBlank(reqVo.getTradeno())) {
            queryWrapper.like("tradeno", reqVo.getTradeno());
        }
        if (StringUtils.isNotBlank(reqVo.getPayStatus())) {
            queryWrapper.eq("pay_status", reqVo.getPayStatus());
        }
        if (StringUtils.isNotBlank(reqVo.getProductName())) {
            List<Integer> orderIdList = jdbcTemplate.queryForList("select mall_sub_order_id from order_item where product_name like ?", Integer.class,
                    "%"+reqVo.getProductName()+"%");
            if(CollectionUtils.isEmpty(orderIdList)){
                queryWrapper.eq("id", 0);
            }else {
                queryWrapper.in("id", orderIdList);
            }
        }
        queryWrapper.orderByDesc("id");
        return page(new Page<>(reqVo.getPageNo(), reqVo.getPageSize()), queryWrapper);
    }
}
